package org.lonetree.experiments;

import java.util.Iterator;
import java.util.Set;
import org.lonetree.tc.core.*;
import org.lonetree.tc.core.Book.Isbn;
import org.lonetree.tc.core.Course.CourseId;
import org.lonetree.tc.core.User.EmailAddress;
import org.lonetree.tc.core.User.Username;
import org.lonetree.tc.core.dao.*;
import org.lonetree.tc.core.exception.*;
import org.lonetree.tc.core.id.ValidatedIdentifier.ValidationException;
import org.lonetree.tc.core.search.BookCriteria;
import org.lonetree.tc.core.search.CourseCriteria;

public class CoreExample{

	public static void main(String[] args){
		DAOFactory fac = DAOFactory.getDAOFactory(DAOFactory.FactoryImplementation.DB_DAO_FACTORY);
		
		try{
//			tryOutUsers(fac);
//			tryOutCourses(fac);
			tryOutBooks(fac);
		}
		catch(Exception e){
			printMessage("Exception caught: <" + e.getClass().getName() + "> " + e.getMessage());
			printMessage("Stack trace:");
			e.printStackTrace();
		}
	}

	private static void tryOutUsers(DAOFactory fac){
		UserDAO userDAO = fac.getUserDAO();
		User.Username username = null;
		User user = null;

//
// CREATE A USERNAME
//
		try{
			username = new User.Username("johnnyboy");
			printMessage("Username created: " + username.getUsernameString());
		}
		catch(ValidationException e){
			printMessage("I'm sorry, that user ID is invalid (" + e.getMessage() + ")");
			e.printStackTrace();
			return;
		}
		
//
// CREATE A NEW USER
//
		try{
			user = userDAO.createUser(username);
			printMessage("User created in persistance layer by DAO: " + user.getUsername().getUsernameString());
		}
		catch(ItemAlreadyExistsException e){
			printMessage("I'm sorry, that user ID already exists");
			return;
		}
		
//		
// GET A USER
//		
		try{
			user = userDAO.getUser(username);
			printMessage("User \"" + user.getUsername().getUsernameString() + "\" was retrieved (expected: \"" + username.getUsernameString() + "\")");
		}
		catch(NoSuchItemException e){
			printMessage("I'm sorry, that user ID does not exist");
			return;
		}
		
		
//
// UPDATE THE USER
//
		try{
			user.setLastName("Martin");
			user.setFirstName("Bojan");
			user.setEmailAddress(new EmailAddress("email@sthg.com"));
			user.setPassword("random");
			userDAO.updateUser(user);
			printMessage("User " + user.getUsername() + " successfully updated");
		}
		catch(NoSuchItemException e){
			printMessage("I'm sorry, that user ID does not exist");
			return;
		}
		catch(AttributeCannotBeNullException e){
			printMessage("I'm sorry, the user cannot be updated without a valid " + e.getAttributeName());
			return;
		}
		catch(ValidationException e){
			e.printStackTrace();
			return;
		}
		
//
// SUSPEND AND UNSUSPEND THE USER
//
		try{
			user.setSuspended(true);
			userDAO.updateUser(user);
			printMessage("User " + user.getUsername() + " successfully suspended and updated");
			
			user.setSuspended(false);
			userDAO.updateUser(user);
			printMessage("User " + user.getUsername() + " successfully unsuspended and updated");
		}
		catch(NoSuchItemException e){
			e.printStackTrace();
			printMessage("I'm sorry, that user ID does not exist");
			return;
		}
		catch(AttributeCannotBeNullException e){
			e.printStackTrace();
		}

//
// REMOVAL OF THE USER
//
		try{
			userDAO.removeUser(user.getUsername());
			printMessage("User " + user.getUsername() + " successfully removed");
		}
		catch(NoSuchItemException e){
			printMessage("I'm sorry, that user ID does not exist");
		}

//
// FIND USERS
//
		try{
			Set<User> users = userDAO.findUsers(null);
			printMessage(users.size() + " users found: ");
			for(Iterator<User> it = users.iterator(); it.hasNext();){
				User u = it.next();
				printMessage("User " + u.getUsername() + ": {" + u.getFirstName() + ", " + u.getLastName() + "}");
			}
		}
		catch(SearchException e){
			e.printStackTrace();
		}
	}
	
	private static void tryOutCourses(DAOFactory fac) throws Exception{
		CourseDAO cd = fac.getCourseDAO();
		try{
			cd.findCourses(new CourseCriteria("cpsc", null, null));
			cd.createCourse(new CourseId("cpsc", (short)333));
		}
		catch(ItemAlreadyExistsException e){
			printMessage("That course already exists");
		}
	}

	private static void tryOutBooks(DAOFactory fac) throws Exception{
		BookDAO bd = fac.getBookDAO();
		try{
			printMessage("Finding all books...");
			Set<Book> books = bd.findBooks(null);
			displayBooks(books);
			
			String searchstr = "The";
			printMessage("Finding all containing the string \"" + searchstr + "\" in the title...");
			books = bd.findBooks(new BookCriteria(null, searchstr, null));
			displayBooks(books);
			
			Book b = bd.createBook(new Isbn("1234567890987"));
			printMessage("Created book with ISBN: " + b.getIsbn().getIsbnString());
			b.setOptional(true);
			b.setTitle("Title");
			b.getAuthors().add("Some author");
			b.getAuthors().add("Some author");
			b.getAuthors().add("Some author2");
			new BookComment(b, fac.getUserDAO().getUser(new Username("bmartin")), "this is a new comment", false);
			bd.updateBook(b);
			
			printMessage("Flagged book comments: " + bd.getFlaggedBookComments().toString());
		}
		catch(ItemAlreadyExistsException e){
			e.printStackTrace();
		}
	}

	private static void displayBooks(Set<Book> books){
		for(Iterator<Book> it = books.iterator(); it.hasNext();){
			Book b = it.next();
			printMessage("Found book with ISBN: " + b.getIsbn() +
					"{\n" + b.getTitle() + ", " + b.getAuthors() + 
					"\n" + b.getComments() + "\n" + b.getSections() + "\n"  + b.getSources() + "\n"  + "}");
		}
	}

	/**
	 * This method prints the message. In reality, it could be anything (probably not a sysout). In a webapp, the message
	 * would be displayed on a web page.
	 *
	 * @param s string to print
	 */
	private static void printMessage(String s){
		System.out.println("<CORE EXAMPLE | " + new java.util.Date().toString() + "> " + s);
	}
}
